#include "amLog.h"
#include <stdarg.h>
#include "wl_queue.h"
#include "comm_data_pack.h"
#include "commInterface.h"

uint8_t g_logout_en = 1;

static   const char* LEVEL = "VDIWFS";
static   uint32_t s_u32LogLevel = AM_LOG_DEFAULT_PRINT_LEVEL;
volatile uint32_t   g_u32ToVcuDmaTxFlg = 0;
volatile uint32_t   g_u32ToApDmaTxFlg = 0;
volatile uint32_t   g_u32ToDbgDmaTxFlg = 0;
volatile uint32_t   g_u32ToTcuDmaTxFlg = 0;


static int32_t __printlogTag(char *ps8LogBuf, char cLevel, uint32_t u32WithTimestamp, const char* ps8Tag)
{
    int32_t  s32Size = 0;
    uint64_t u64Time;
    if (1 == u32WithTimestamp)
    {
        u64Time = getSystemTimestamp();
        //s32Size = snprintf(ps8LogBuf, BUF_LOG_ITEM_SIZE, "%lu%lu %c %s ", (unsigned long)NUBER64_H(u64Time), (unsigned long)NUBER64_L(u64Time), cLevel, ps8Tag);
        s32Size = snprintf(ps8LogBuf, BUF_LOG_ITEM_SIZE, "%ld%03d %c %s ", (uint32_t)(u64Time/1000), (uint16_t)(u64Time%1000), cLevel, ps8Tag);
    }
    else if (2 == u32WithTimestamp) // without timestamp
    {
        s32Size = snprintf(ps8LogBuf, BUF_LOG_ITEM_SIZE, "%c %s ", cLevel, ps8Tag);
    }
    else
    {
        // clear log
        // here to matain the same logic with before
        // if(iap_data.ota_status == 1)
        // {
        //     s32Size = -1; 
        // }
    }

    return s32Size;
}

static void __copylogtoRingBuf(char *ps8LogBuf, int32_t s32Len)
{
    // packLog2Ap((uint8_t*)ps8LogBuf, s32Len, COMM_ECU_LOG, COMM_CMD_CAMP_WR_NR, ID_SELF, ID_MR813);
    commTxRingPush(DEBUG_COMM_TYPE, (uint8_t*)ps8LogBuf, s32Len, 0);
}

void log_print(uint32_t u32Level, uint32_t u32WithTimestamp, const char* ps8Tag, const char* ps8Format, ...)
{
    char as8TempBuf[BUF_LOG_ITEM_SIZE];
    int32_t s32Size = 0;
    int32_t s32Len = 0;
    va_list ap;

    if((u32Level < s_u32LogLevel) || (0 == g_logout_en))
    {
        return;
    }

    // print to temp buffer    
    s32Size = __printlogTag(as8TempBuf, LEVEL[u32Level], u32WithTimestamp, ps8Tag);
    if (s32Size < 0)
    {
        return;
    }
    s32Len += s32Size;

    va_start(ap, ps8Format);
    s32Size = vsnprintf(as8TempBuf + s32Size, (BUF_LOG_ITEM_SIZE - s32Size), ps8Format, ap);
    va_end(ap); 

    if (s32Size < 0) 
        return;

    s32Len += s32Size;
    if (s32Len > BUF_LOG_ITEM_SIZE)
	{
        s32Len = BUF_LOG_ITEM_SIZE;
	}

    __copylogtoRingBuf(as8TempBuf, s32Len);
}

int32_t LOG_STRH(uint32_t u32Level, uint32_t u32WithTimestamp, const char* ps8Tag, const uint8_t *data_p, int32_t len) 
{
    char as8TempBuf[BUF_LOG_ITEM_SIZE];
    int32_t s32Size = 0;
    int32_t s32Len = 0;

    if((u32Level < s_u32LogLevel) || (0 == g_logout_en))
    {
        return -1;
    }

    // print to temp buffer    
    s32Size = __printlogTag(as8TempBuf, LEVEL[u32Level], u32WithTimestamp, ps8Tag);
    if (s32Size < 0)
    {
        return -1;
    }
    s32Len += s32Size;

    if (len > BUF_LOG_ITEM_SIZE-s32Len)
    {
        len = BUF_LOG_ITEM_SIZE - s32Len;
    }

    memcpy(as8TempBuf + s32Len, data_p, len);

    s32Len += len;
    __copylogtoRingBuf(as8TempBuf, s32Len);

    return len;
}


int32_t LOG_STR(const uint8_t *data_p, uint32_t len) 
{
    if (0 == g_logout_en)
    {
        return -1;
    }

    if (len > BUF_LOG_ITEM_SIZE)
    {
        len = BUF_LOG_ITEM_SIZE;
    }

    __copylogtoRingBuf((char*)data_p, len);

    return len;
}

int32_t LOG_HEX(const uint8_t *data_p, uint32_t len, uint32_t withTail)
{
    char as8TempBuf[BUF_LOG_ITEM_SIZE];
    int32_t s32Len = 0;

    if (0 == g_logout_en)
    {
        return -1;
    }

    if (len > BUF_LOG_ITEM_SIZE-2)
    {
        len = BUF_LOG_ITEM_SIZE-2;
    }
    
    for (uint8_t i = 0; i < len; i++)
    {
        s32Len += sprintf(as8TempBuf + s32Len, "%02x ", data_p[i]);
    }

    if(1 == withTail)
    {
        as8TempBuf[s32Len++] = '\r';
        as8TempBuf[s32Len++] = '\n';
    }
    // copy to ring buffer and send msg
    __copylogtoRingBuf(as8TempBuf, s32Len);

    return len;
}

void set_log_level(uint8_t level)
{
    if(level <= AM_LOG_LEVEL_MAX)  
    {
        s_u32LogLevel = level;
    }
}

uint8_t get_log_level(void)
{ 
    return s_u32LogLevel;
}

uint8_t get_log_switch(void)
{
    return g_logout_en;
}
